package com.zhentao.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhentao.channel.TbChanFiles;
import com.zhentao.channel.TbChannel;
import com.zhentao.dto.FilesDto;
import com.zhentao.files.TbFiles;
import com.zhentao.files.TbWarehouse;
import com.zhentao.files.param.FilesParam;
import com.zhentao.mapper.TbChanFilesMapper;
import com.zhentao.mapper.TbChannelMapper;
import com.zhentao.mapper.TbFilesMapper;
import com.zhentao.mapper.TbWarehouseMapper;
import com.zhentao.minio.service.impl.MinioFileStorageServiceImpl;
import com.zhentao.service.FilesAutoScanService;
import com.zhentao.service.TbChanFilesService;
import com.zhentao.service.TbFilesService;
import com.zhentao.user.UserHolder;
import com.zhentao.utils.AppHttpCodeEnum;
import com.zhentao.utils.ResponseResult;
import com.zhentao.files.vo.FilesVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static com.zhentao.common.Constans.*;
import static com.zhentao.common.Constans.FILES_REDIS;

@Service
public class TbFilesServiceImpl extends ServiceImpl<TbFilesMapper, TbFiles>
        implements TbFilesService {

    @Autowired
    private TbFilesMapper tbFilesMapper;
    @Autowired
    private TbChanFilesService tbChanFilesService;
    @Autowired
    private TbChanFilesMapper tbChanFilesMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private TbWarehouseMapper tbWarehouseMapper;
    @Autowired
    private TbChannelMapper channelMapper;
    @Autowired
    private MinioFileStorageServiceImpl minioFileStorageService;
    @Autowired
    private FilesAutoScanService filesAutoScanService;
    // 定义一个线程池，调整线程数量
    private static final ExecutorService executorService = Executors.newFixedThreadPool(5);

    /**
     * @param param
     * @return com.zhentao.utils.ResponseResult
     * @description 上传档案
     * @author 振涛教育_小Q
     * @date 2024/12/7 21:41
     */
    @Override
    @Transactional
    public ResponseResult uploadFiles(FilesParam param) {
        boolean flag = false;
        // 判断参数是否有效
        if (param == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_NULL);
        }
        // 向仓库中添加资源
        TbWarehouse warehouse = new TbWarehouse();
        // 设置参数
        // 处理图片集合
        List<String> images = param.getImageUrl();
        // 存储处理完成的图片
        List<String> imagePathMinio = new ArrayList<>();
        if (images != null && images.size() > 0) {
            List<CompletableFuture<Void>> futures = new ArrayList<>();
            for (String image : images) {
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    try {
                        String uuid = UUID.randomUUID().toString(true);
                        FileInputStream inputStream = new FileInputStream("C:\\Users\\lenovo\\Pictures\\Screenshots" + "\\" + image);
                        String path = minioFileStorageService.uploadImgFile("imageText", uuid + ".jpg", inputStream);
                        // 合并转换为JSON串
                        imagePathMinio.add(path);
                        String join = StringUtils.join(imagePathMinio, ",");
                        warehouse.setImage(join);
                    } catch (FileNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                }, executorService);
                futures.add(future);
            }
            // 等待所有异步任务完成
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        }

        // 处理语音集合
        List<String> speechDescritpion = param.getSpeechDescritpion();
        if (speechDescritpion != null && speechDescritpion.size() > 0) {
            String speechDescriptionText = StringUtils.join(speechDescritpion, ",");
            warehouse.setContent(speechDescriptionText);
            // 判断description字段是否为null，如果为null就不需要与集合拼接，如果不为null就两个拼接在一起
            if (param.getDescription() != null) {
                String descriptionText = param.getDescription() + speechDescriptionText;
                warehouse.setContent(descriptionText);
            }
        }
        if (speechDescritpion.size() == 0) {
            warehouse.setContent(param.getDescription());
        }
        // 视频路径处理  从redis中获取
        String vedioPath = redisTemplate.opsForValue().get(VEDIO_PREFIX_REDIS);
        System.err.println(vedioPath);
        if (vedioPath != null) {
            warehouse.setVideoContent(vedioPath);
        }
        // 手绘图片处理
        String handPath = redisTemplate.opsForValue().get(HAND_PREFIX_REDIS);
        System.err.println(handPath);
        if (handPath != null) {
            warehouse.setPlanContent(handPath);
        }
        // 仓库添加
        tbWarehouseMapper.insert(warehouse);

        // 档案表添加  以及添加类型
        TbFiles tbFiles = new TbFiles();
        tbFiles.setTitle(param.getTitle());
        tbFiles.setPublishDate(param.getPublishDate());
        // 默认为 待审核
        if (param.getStatus() != null) {
            tbFiles.setStatus(param.getStatus());
        }
        // 用户id
        String userId = UserHolder.getUser().getId();
        if (userId != null) {
            tbFiles.setUId(Integer.valueOf(userId));
        }
        tbFiles.setWId(warehouse.getId());
        // 添加档案
        flag = this.save(tbFiles);
        // 中间表添加
        List<Integer> channels = param.getChannels();
        System.err.println(tbFiles.getId());
        if (channels != null && channels.size() > 0) {
            tbChanFilesMapper.insertTypeId(tbFiles.getId(), channels);
        }
        // 对文章进行系统自动审核
        filesAutoScanService.autoScanFiles(tbFiles.getId());

        return flag ? ResponseResult.okResult(AppHttpCodeEnum.SUCCESS) : ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
    }


    /**
     * @param file
     * @return com.zhentao.utils.ResponseResult
     * @description 读图文文件
     * @author 振涛教育_小Q
     * @date 2024/12/7 21:41
     */
    @Override
    public ResponseResult uploadImage(MultipartFile file) {
        return ResponseResult.okResult("上传成功");
    }

    @Override
    public ResponseResult select(FilesDto fileDto) {
        // 获取当前登录用户id
        String userId = UserHolder.getUser().getId();
        List<Long> filesIds = new ArrayList<>();
        Page<TbFiles> page = new Page<>(fileDto.getPageNum(), fileDto.getPageSize());
        if (fileDto.getTypeIds() != null && fileDto.getTypeIds().size() > 0) {
            // 获取对应档案id集合
            filesIds = getFilesIds(fileDto);
        }
        this.page(page, Wrappers.<TbFiles>lambdaQuery()
                .eq(com.baomidou.mybatisplus.core.toolkit.StringUtils.checkValNotNull(userId),
                        TbFiles::getUId, Integer.valueOf(userId))
                .like(com.baomidou.mybatisplus.core.toolkit.StringUtils.checkValNotNull(fileDto.getTitle()),
                        TbFiles::getTitle, fileDto.getTitle())
                .between(com.baomidou.mybatisplus.core.toolkit.StringUtils.checkValNotNull(fileDto.getPublishDateStart())
                                && com.baomidou.mybatisplus.core.toolkit.StringUtils.checkValNotNull(fileDto.getPublishDateEnd()),
                        TbFiles::getPublishDate, fileDto.getPublishDateStart(), fileDto.getPublishDateEnd())
                .in(filesIds.size() > 0, TbFiles::getId, filesIds)
                .orderByDesc(TbFiles::getPublishDate));

        List<TbFiles> records = page.getRecords();
        for (int i = 0; i < records.size(); i++) {
            TbFiles files = records.get(i);
            FilesVo vo = new FilesVo();
            BeanUtils.copyProperties(files, vo);
            if (files.getWId() != null) {
                // 对vo类进行赋值
                filesCopyToVo(files, vo);
            }
            if (files.getId() != null) {
                // 对应的类型id
                List<TbChanFiles> chanFiles = tbChanFilesMapper.selectList(Wrappers.<TbChanFiles>lambdaQuery()
                        .eq(TbChanFiles::getFilesId, files.getId()));
                // 获取类型集合
                List<TbChannel> channelNames = vo.getChannelNames();
                if (chanFiles != null && chanFiles.size() > 0) {
                    for (TbChanFiles chanFile : chanFiles) {
                        TbChannel tbChannel = channelMapper.selectById(chanFile.getTypeId());
                        channelNames.add(tbChannel);
                    }
                }
            }
            records.set(i, vo);
        }
        return ResponseResult.okResult(page);
    }


    /**
     * @param files
     * @param vo
     * @return void
     * @description 对vo类型进行赋值
     * @author 振涛教育_小Q
     * @date 2024/12/9 16:47
     */
    private void filesCopyToVo(TbFiles files, FilesVo vo) {
        TbWarehouse warehouse = tbWarehouseMapper.selectById(files.getWId());
        // 每次在查询出来图片的时候，进行一个，分割
        if (warehouse.getImage().contains(",")) {
            List<String> images = vo.getImages();
            String[] imageSplit = warehouse.getImage().split(",");
            if (imageSplit.length > 0) {
                images.addAll(Arrays.asList(imageSplit));
            }
        } else {
            vo.setImage(warehouse.getImage());
        }
        if (warehouse.getContent() != null) vo.setContent(warehouse.getContent());
        if (warehouse.getVideoContent() != null) vo.setVideoContent(warehouse.getVideoContent());
        if (warehouse.getPlanContent() != null) vo.setPlanContent(warehouse.getPlanContent());
    }

    /**
     * @param fileDto
     * @return java.util.List<java.lang.Long>
     * @description 获取中间表对应的档案id集合
     * @author 振涛教育_小Q
     * @date 2024/12/9 16:46
     */
    private List<Long> getFilesIds(FilesDto fileDto) {
        List<Long> filesIds;
        List<Integer> typeIds = fileDto.getTypeIds();
        filesIds = tbChanFilesMapper.selectList(Wrappers.<TbChanFiles>lambdaQuery()
                .in(TbChanFiles::getTypeId, typeIds)).stream().map(TbChanFiles::getFilesId).collect(Collectors.toList());
        return filesIds;
    }

    @Override
    public ResponseResult updateFile(TbFiles tbFiles) {
        if (tbFiles.getStatus() == 1) {
//            修改文章
            tbFilesMapper.updateById(tbFiles);
//            修改文章和频道中间表
            tbChanFilesMapper.shanchu(tbFiles.getId());
            TbChanFiles tbChanFiles = new TbChanFiles();
            tbChanFiles.setTypeId(tbFiles.getTypeId());
            tbChanFiles.setFilesId(tbFiles.getId());
            tbChanFilesService.save(tbChanFiles);
            return ResponseResult.okResult(200, "修改成功");
        } else {
            return ResponseResult.errorResult(400, "修改失败,下架的商品不能进行修改");
        }


    }

    //    上架
    @Override
    public ResponseResult shang(Long id) {
        TbFiles tbFiles = new TbFiles();
        tbFiles.setId(id);
        tbFiles.setStatus(1);
        boolean b = this.updateById(tbFiles);
        return b ? ResponseResult.okResult(200, "上架成功") : ResponseResult.errorResult(400, "上架失败");
    }

    @Override
    public ResponseResult xiajiaa(Long id) {
        TbFiles tbFiles = new TbFiles();
        tbFiles.setId(id);
        tbFiles.setStatus(2);
        boolean b = this.updateById(tbFiles);
        return b ? ResponseResult.okResult(200, "下架成功") : ResponseResult.errorResult(400, "下架失败");
    }

    @Override
    public ResponseResult shanchur(Integer id) {
        boolean b = this.removeById(id);
        return ResponseResult.okResult(b);
    }

    @Override
    public ResponseResult gongkai(FilesDto fileDto) {
        return null;
    }
}




